package com.wangfei.lecture.SM;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;

public class SM2Key {

    private static KeyPair generateInnerSm2KeyPair() {
        try {
            final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
            // 获取一个椭圆曲线类型的密钥对生成器
            final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
            SecureRandom random = new SecureRandom();
            // 使用SM2的算法区域初始化密钥生成器
            kpg.initialize(sm2Spec, random);
            // 获取密钥对
            KeyPair keyPair = kpg.generateKeyPair();
            return keyPair;
        } catch (Exception e) {
            System.out.println("generate sm2 key pair failed: "+ e.getMessage());
        }
        return null;
    }

    /**
     * 生成byte[]格式sm2公私钥方法入口
     * @return
     */
    public static ByteKeyPair generateSm2Keys(){
        KeyPair sm2KeyPair = generateInnerSm2KeyPair();
        BCECPrivateKey privateKey = (BCECPrivateKey) sm2KeyPair.getPrivate();
        BCECPublicKey publicKey = (BCECPublicKey) sm2KeyPair.getPublic();
        ByteKeyPair result = new ByteKeyPair(publicKey.getQ().getEncoded(false), privateKey.getD().toByteArray());
        return result;
    }

    /**
     * hex格式公钥转换成pem格式公钥
     * @param hexPublicKey
     * @return
     */
    public static String hexSm2PublicKeyToPem(String hexPublicKey){
        //补充硬加密的头
        String hexHead="3059301306072a8648ce3d020106082a811ccf5501822d034200";
        String hexKey = hexHead+hexPublicKey.replaceAll(" ","");
        //两个拼起来转base64
        String base64Fulfill = Base64.encodeBase64String(Hex.decode(hexKey));
        String sm2PemKey = "-----BEGIN PUBLIC KEY-----"+base64Fulfill+"-----END PUBLIC KEY-----";
        return sm2PemKey;
    }

    /**
     * pem格式公钥转换成hex格式公钥
     * @param pemPublic
     * @return
     */
    public static String pemSm2PublicKeyToHex(String pemPublic) {
        String base64PriBytes = pemPublic.replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "").trim();
        byte[] base64temp = Base64.decodeBase64(base64PriBytes);
        return Hex.toHexString(base64temp).substring(52);
    }
}
